home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-02-12 | 40.7 KB | 1,043 lines |
- Wheaton Strings library documentation
-
- October 10, 1989
- February 20, 1991 (minor update)
- May 15, 1992 (minor update)
- October 20, 1992 (minor update)
- January 27, 1993 (add String40 and String120 - fix some documentation bugs)
-
- Copyright (c) 1992, 1993 by Paul Wheaton
-
- Note that this documentation does not cover all of the features of the
- provided in this library. For that, you will have to look at the header files.
-
- The Wheaton Libraries are shareware. Anyone may use the libraries provided
- that they do not change them. If you want to change them or if you want
- phone support from me, you must pay $50. This in the hope that the hundreds
- of vendors that are creating their own string libraries can go with just
- one - I'm pretty tired of getting a library in that seems like it will be
- pretty cool, just to find out that it uses the same identifiers as
- something else and there are then link conflicts.
-
- For those programmers that never read documentation but have
- mysteriously made it this far, just look quickly at section 1.1.4 and
- 5.1. To make these libraries available, you need to include
- <Strings.h> link with WLIB.LIB and FATAL.OBJ (or WW.LIB which includes
- a different FATAL.OBJ).
-
- This Strings library, consisting of one class and a few independent
- functions, provides an easier, more intuitive way to manipulate
- strings. By including this stuff into your programs you can use (or
- create!) functions that do not need chunks of memory pre-allocated for
- them. Concatenation is done with "+" or "+=" instead of "strcat".
- Comparison is done with "==", "!=", "<", etc. instead of "strcmp".
- Source ends up being more readable, and less verbose. Many common
- string manipulation errors are completely eliminated. For programmers
- new to "C", these libraries provide more functionality with fewer
- operators to memorize, thus reducing the dreaded learning curve.
-
- (note - there is now more than one class, but you may treat the class
- "String" as if it were just one. Later, when you have more experience, you
- can use the classes String40 and String120 for optimization)
-
- Strings are automatically converted from type String to char* and back
- as needed. The two types can often be mixed to give the same results.
-
-
- Strings
- 1 Advantages over C
- 1.1 for programmers new to C
- 1.1.1 less to memorize
- 1.1.2 more intuitive
- 1.1.3 similar to other languages
- 1.1.4 faster to learn
- 1.2 for old C programmers
- 1.2.1 less to type
- 1.2.2 less worry about low level stuff: concentrate more on program
- 1.2.3 more readable
- 1.2.4 eliminate overflow errors
- 1.2.5 faster executable
- length does not need to be calculated
- 1.2.6 use less memory
- don't need to allocate memory to cover "worst case"
- 1.2.7 functions that are more independent (don't need storage space)
- 2 Disadvantages from C
- 2.1 speed overhead
- allocating memory in the heap at creation and appending
- 2.2 storage overhead
- storing length and extra pointers
- 3 A little bit about how this works
- 4 Implementing this with char* for optimal performance
- 5 Functions
- 5.1 String class member functions
- 5.1.1 declaring a String
- 5.1.1.1 based on a given string constant or char*
- 5.1.1.2 based on a character
- 5.1.1.3 based on another String
- 5.1.1.4 without initialization
- 5.1.1.5 extra allocation
- 5.1.2 Length() or Size()
- 5.1.3 + (concatenation)
- 5.1.4 += (appending form of concatenation)
- 5.1.5 = (assignment) and conversions
- 5.1.6 ==,!=,<,>,<=,>= (comparison)
- 5.1.7 () or At() (retrieving substrings)
- 5.1.7.1 Before(), Through(), From() and After()
- 5.1.8 [] (String char reference)
- 5.1.9 Left(), Right(), Center(), Just() (justification)
- 5.1.10 Capacity() (report current allocation)
- 5.1.11 ReAlloc() (change capacity)
- 5.1.12 ToLower() (force all upper case letters to lower case)
- 5.1.13 ToUpper() (force all lower case letters to upper case)
- 5.1.14 Index() (find the index of a char)
- 5.1.15 Insert() (insert a char or a sting into the string)
- 5.1.16 Delete() (delete characters from the string)
- 5.2 non-member functions
- 5.2.1 Str() (convert integers to String)
- 5.2.2 Form() (convert reals to a String using a format)
- 5.2.3 StringOf() (return a string of chars)
- 5.2.4 Spaces() (return a String of a certain number of spaces)
- 5.2.5 LeftText(), RightText(), CenterText(), JustText()
-
-
-
- 1 Advantages over C
-
- I hope to show that using these String libraries in C++ is a great deal
- easier than using the ANSI C string libraries or any string library that
- could possibly be written in C. It is my opinion that productivity in
- string manipulation development will increase by a factor of four for
- those application programmers that use this library.
-
- 1.1 for programmers new to C
-
- Any time that you move to a new language there will be a learning curve.
- C is notorious for being too terse and, thus, hard to read and tougher to
- learn. Much of this has to do with being a "mid level language": Easier
- to work with than assembly yet harder than "high level languages" such as
- Pascal or FORTRAN. C gains you a great deal of portability and runtime
- effeciency over most "high level languages". C++ with a healthy set of
- libraries provides all of the advantages of C coupled with the advantages
- of a high level language. This library should make string manipulation
- easier than not only C, but FORTRAN, Pascal, BASIC, LISP or Modula-2. A
- programmer new to this library will probably find all of the string
- manipulation features that they appreciated most in their favorite
- languages and then some new twists that will make their programming lives
- even easier.
-
- 1.1.1 less to memorize
-
- C++ cures some of the idiosyncrasies of C that directly effect
- string manipulation libraries, one of the worst being the pointer to
- a character concept. In order for a programmer to keep from getting
- into trouble when manipulating strings in C, they must memorize how
- the compiler handles them (the strings): C Strings are an array of
- characters terminated by a null character; strings are referenced by
- a pointer to the first element of the string; runtime range checking
- is not standard and is performed with library routines when the size
- of the string is passed.
-
- In this library, how the String is actually stored and manipulated
- is hidden from the applications programmer. Runtime range checking
- is performed by the library so the applications programmer can
- concentrate on their application rather than monitor the size of
- their strings and make sure everything will fit. Since string
- manipulation using this library is similar to working with numbers
- in C or C++, all of the exceptions for plain C string handling never
- have to be learned.
-
- 1.1.2 more intuitive
-
- ANSI C maintains a great deal of exceptions when it comes to string
- handling. For example, if you have two strings, S1 and S2,
- assignment of one from the other does not result in two identical
- copies of the string, it results in two pointers pointing to the
- same string: Modifying one effects the other. Generally, when an
- assignment is made such as X=Y, the contents of X are separate from
- Y yet the same. This library supports the more intuitive assignment
- operation as well as other operators and functions that any string
- library *ought* to have.
-
- 1.1.3 similar to other languages
-
- Of course, all of the functions and operators available in C are
- also available in C++. Many of them (C functions) will work with
- the String type as well as good ole char*.
-
- In Turbo Pascal
-
- Var S1,S2:String;
- Begin
- S1:="oatmeal";
- S2:="I like "+S1+".";
- End;
-
- In BASIC
-
- 550 S1$="oatmeal"
- 560 S2$="I like "+S1$+"."
-
- In FORTRAN
-
- char S1*8
- char S2*16
- S1='oatmeal'
- S2='I like ' // S1 // '.'
-
- In C (or C++ without this library)
-
- char* S1="oatmeal";
- char S2[16];
- strcpy(S2,"I like ");
- strcat(S2,S1);
- strcat(S2,".");
-
- or...
-
- char* S1="oatmeal";
- char S2[16];
- sprintf(S2,"I like %s.",S1);
-
- With this library...
-
- String S1="oatmeal";
- String S2="I like "+S1+".";
-
- As I hope you can see, this library's operators and functions
- provide a string manipulation library that implements the best and
- most common parts of other languages. You should find that using
- this library with C++ is a great deal simpler, more readable and
- more powerful than what you were using before.
-
- 1.1.4 faster to learn
-
- Given the aforementioned points, it ought to be clear that learning
- how to use this library will take a small fraction of the time it
- would take to learn ANSI C string manipulation. For most
- applications all you need to know is that "String" is the
- constructor, "=" is assignment and "+" is concatenation. Also,
- anything that *seems* like it should work, probably will; if it
- *seems* like there should be a function to handle a certain case,
- there probably is.
-
- 1.2 for old C programmers
-
- Don't fret! This library is completely compatible with the old
- char* stuff. You only need to use it when it's convenient to you.
- After a while, I hope that you'll use it 99% of the time (yes there
- are a few times when using char* could save some execution time or
- storage space). For the most part, I think you'll find that this
- stuff cuts your development time to a third (maybe a quarter!) of
- what it used to be in string manipulation.
-
- 1.2.1 less to type
-
- Since C++ allows access to define operators, then the ANSI functions
- to do string comparisons and the like can be circumvented for the
- more convenient notations.
-
- Notation for assignment
-
- in C : strncpy(S1,S2,sizeof(S1));
- in C++: S1=S2;
-
- Concatenation
-
- in C : strncat(S1,strncat(S2,S3,sizeof(S2)),sizeof(S1));
- or : sprintf(S1,"%s%s%s",S1,S2,S3);
- in C++: S1+=S2+S3;
-
- Comparison
-
- in C : strcmp(S1,S2)<0
- in C++: S1<S2
-
- 1.2.2 less worry about low level stuff: concentrate more on program
-
- Without this library there is the frequent need of application programmer
- range checking: Making sure that arrays are declared of sufficient size;
- indexing is within bounds; using the appropriate function/operator on the
- appropriate structure (such as sizeof on char* vs. char[x]).
-
- With this library, nearly all of these problems are eliminated.
- Being a higher level set of functions and operators, the
- applications programmer spends a great deal less time worrying about
- how the strings are stored and maintained and is given more time to
- solving the problem at hand.
-
- Expanding an earlier example:
-
- (Example 1.2.2)
-
- The purpose here is to assign a string to all three strings and then
- concatenate them all together, storing the result in the first
- string.
-
- ANSI C, style 1
-
- 1 | char S1[18];
- 2 | char S2[13];
- 3 | char* S3=" mice.";
- 4 | strcpy(S1,"Three");
- 5 | strcpy(S2," blind");
- 6 | strncat(S1,strncat(S2,S3,sizeof(S2)),sizeof(S1));
-
- ANSI C, style 2
-
- 11 | char S1[18];
- 12 | char* S2=" blind";
- 13 | char* S3=" mice.";
- 14 | strcpy(S1,"Three");
- 15 | sprintf(S1,"%s%s%s",S1,S2,S3);
-
- C++ with Strings library
-
- 21 | String S1="Three";
- 22 | String S2=" blind";
- 23 | String S3=" mice.";
- 24 | S1+=S2+S3;
-
- Note that in lines 1 and 2, the applications programmer needed to
- decide whether char* or char[x] could be used and, if the latter,
- how much storage was going to be needed. In style 1, S2 needed to
- be defined as an array because part of the concatenation process was
- going to involve storing a concatenated result in S2. There were
- ways to avoid this while still avoiding the use of sprintf such as
- concatenating S1 to S2 and then S1 to S3. On those lines where
- "char* S=" was used, "static char S[]=" could have been used. Also,
- the programmer could choose to use strcat instead of strncat and
- thus avoid the use of sizeof, but if they modified some code, they
- may forget to expand their arrays and overwrite memory. On the other
- hand, sometimes when a programmer types in one of these function
- calls they insert the wrong variable into sizeof and the problems
- may not show up till years later. In style 2, not only is there the
- same allocation problem for S1, but there is also the issue of
- memorizing the use of sprintf: The parameter order and the effects
- of special characters in the form string. Also, modifications beg
- for runtime crashes: If another string is needed and specified in
- the form string as "%s%s%s%s" yet the new parameter is not added,
- this can result in many, less than predictable results. These are
- all things that the programmer must always consider when
- manipulating strings in C.
-
- In C++, using this library, the applications programmer has no *need*
- to worry about the declaration size of a string: Resizing is done
- dynamically. Any sort of modification can be made to this piece of
- code as far as adding new strings and the like without having to be
- sure to change the code somewhere else too.
-
- 1.2.3 more readable
-
- Although readability is known in programming circles as a "religious
- issue", I think many (if not all) programmers can agree that this
- library is more readable than any library that can be created in
- ANSI C.
-
- Strings are treated a great deal more like other built-in (atomic)
- types of C, such as numbers. Therefore they do not carry all of the
- exceptions that ANSI C string structures (which are a combination of
- two atomic types: the char and the pointer) do. Further, defining
- the object as a String better clarifies the intent. "String S;" says
- that S is a string, whereas "char* S;" says that S is a pointer to a
- character which the programmer must know can be used to handle a
- string or, more simply, as a pointer to a single char or an array of
- chars that is not to be used as a string.
-
- From example 1.2.2:
-
- ANSI C, style 1, line 6
- strncat(S1,strncat(S2,S3,sizeof(S2)),sizeof(S1));
-
- ANSI C, style 2, line 15
- sprintf(S1,"%s%s%s",S1,S2,S3);
-
- C++ with Strings library, line 24
- S1+=S2+S3;
-
- Just comparing these three lines of code in size tells you that the
- first two are going to take longer to read than the last just
- because there are more characters (Their size, in characters, is 49,
- 30 and 10, respectively). In the first line, there are two function
- calls (strncat), two operator calls (sizeof), two of the variables
- are referenced twice and a whole mess of parentheses. In the second
- line there are two references to S1 and the form string ("%s%s%s")
- which, when debugging, needs to be compared to the following
- parameters to be sure that there are the same number of parameters
- as "%s"s. I think that the last line is about as plain and easy to
- understand as it could get. What is happening is very quick to read
- and easier to understand. There is no place in this line that a
- conflicting error could occur (such as a sizeof on the wrong var in
- the first line or a "%s" without a matching argument in the second).
-
- 1.2.4 eliminate overflow errors
-
- An ANSI C string programming problem that is pretty hard to track
- down is when a user feeds a program a string that is bigger than the
- applications programmer expected to have that string ever hold. The
- result is that data is written where other data is supposed to be
- stored. This can lead to anything from some garbled data to a
- system crash.
-
- By using the "String" type of this library, this problem is avoided.
- when an attempt is made to store more string than will fit into the
- current allocation, more space is allocated and the string is stored
- there.
-
- 1.2.5 faster executable
-
- I have to admit that generally, this string stuff has a slight speed
- overhead. However, there is at least one case where speed can
- obviously be improved: The length of the string is always known and
- does not need to be calculated.
-
- A good example of where this pays off is in a loop where the
- programmer wants to examine every character in a string.
-
- In C:
-
- char* S;
- ...
- for(I=0;I<strlen(S);I++)
- ...
-
- In C++ with this library
-
- String S;
- ...
- for(I=0;I<S.Len();I++)
- ...
-
- In the first example, the length of the string is re-calculated with
- every pass through the loop whereas in the second example the string
- length is retrieved from a value stored in memory. Of course, an
- alert C programmer can repair the problem with the first example by
- storing the length in a temporary variable before the loop is
- executed.
-
- Other than that, what would save execution time is fewer function
- calls with shorter, fewer parameters.
-
- 1.2.6 use less memory
-
- Again, don't misinterpret this: There's also a slight memory
- overhead in most cases. The exceptions are that: Programmers don't
- need to over allocate memory to cover "worst case"; fewer function
- calls with fewer parameters make for less code space.
-
- For example, say a string is passed to a function that can be any
- size from 5 to 1005 and the first thing that needs to be done is to
- make a local copy of that string. Also, the function is going to
- modify the string such that it may grow and shrink within a range of
- 5 to 2005 chars. In C, the proper thing to do is to allocate a
- chunk of memory that can hold 2005 characters. With this library
- you just assign the given string to a new one and the new string
- will automatically be the current size and as modifications are
- made, it will grow as needed. If most calls to this function pass
- strings of length 10 and have internal strings resulting in a length
- of 15, then the C stuff will have wasted almost 2000 bytes of memory
- while this library will be using just a few bytes over 15.
-
- 1.2.7 functions that are more independent (don't need storage space)
-
- If you write a function that returns a string in ANSI C, then you
- first need to receive a pointer to a place in memory where you can
- store the resulting string. In C++ with this library, you can just
- return a "String" object without first being passed a chunk of
- memory. For example, say I want a function called Str, that when
- passed an integer, would return a string. A possibility in C is
- "char* Str(long Num, char* S)". When calling this function, the
- programmer must allocate enough space to store the resulting string
- and pass a pointer to this area via the second parameter. That same
- pointer will be returned on exit. This is a lot of extra hassle for
- the applications programmer. In C++ with this library you can have
- "String Str(long Num)". The storage space is created dynamically
- and the result is passed to whatever does the calling. The
- applications programmer does not need to bother with preparing
- storage space for the result.
-
- 2 Disadvantages from C
-
- I think that 95% of the time, the advantages of using this library
- far outweigh the disadvantages. Also, I think, 99% of the time,
- the disadvantages are negligable, non-existent or compensated for.
- Note that as a programmer becomes more familiar with this library,
- there are ways to optimize a mix between this code and the
- old char* stuff for better performance and space savings.
-
- 2.1 speed overhead
-
- Every time a string is created and sometimes when a string is
- expanded in size, memory needs to be allocated. When the string is
- disposed of, that memory needs to be reclaimed. This memory
- management does take up time. Also, several of the functions need
- to take a little time to modify a local variable to keep track of
- the length.
-
- 2.2 storage overhead
-
- Not only does a "String" store all that a "char[]" does, it also
- keeps an extra pointer and two integers (keep in mind that with any
- C++ class, how an object is stored and its methods may change). A
- large array of short strings would probably save a lot of space if
- the char* type was used instead of the String type.
-
- 3 A little bit about how this works
-
- Keep in mind that while the interface to this library will probably
- weather time pretty well, always be prepared for some changes. How
- it works internally probably *will* change although some of the
- concepts may stay the same. As with any C++ class library, you may
- depend on the interface staying the same, but *never* depend on the
- internal workings and storage staying the same: If you happen to
- discover how things are stored and processed internally and access
- those values or methods directly, you'll probably regret it later.
- Now, although I'm about to explain how some of the internal stuff
- works, this is to help you decide how to best optimize your own
- code, not so that you can modify this library or its private data.
-
- When a String is declared
-
- String S="Foo";
-
- 8 bytes are taken up on the stack and 19 are taken up on the heap.
- The C++ heap management system may also have taken up some memory
- for housekeeping so that the heap memory can be cleanly reclaimed.
- Some time is taken to do the heap allocation, to record the length
- of the string, the amount of memory allocated, the location of the
- heap storage space and then to copy the string constant into the
- heap with the null terminator.
-
- Now, say we append to this string
-
- S+="Bar";
-
- The string constant, with its null terminator, is quickly copied
- into the heap immediately after "Foo" and the string length status
- is incremented by 3. There are now 12 bytes free on the heap
- already allocated for use for this string. 6 bytes of the heap
- space is used for the string and 1 is used for the null terminator.
-
- S+=" is derived from the acronym FUBAR.";
-
- The concatenation function recognizes that the amount of memory
- needed to store the resulting string is 40 bytes. 19 is currently
- allocated. 55 bytes of a new storage area is allocated. The text
- "FooBar" is copied from the old storage area to the new storage
- area. The string constant, with its null terminator, is now copied
- into the new storage area following "FooBar". The old storage area
- is released back to the heap. The local storage area pointer is set
- to point at the new storage area. The size of the new storage area
- is recorded. The length status is incremented to 39.
-
- 4 Implementing this with char* for optimal performance
-
- By reading the previous section on how the internals of this library
- work, it should be clear that declaring a string of type String that
- is initialized and referenced, yet never modified, may be a waste of
- time and space. Say you have a small bit of code:
-
- void Foo(const char*);
- void Bar(const char*);
- ...
- String S="DooDah";
- Foo(S);
- Bar(S);
-
- When S is constructed, it takes some time and space to get set up
- and then just passes a pointer to its local copy of "DooDah" to Foo
- and Bar. If S were set up as
-
- char* S="DooDah";
-
- instead, then there would be absolutely no time or space spent on
- construction. S would be calculated at compile time rather than run
- time and is the exact type as what is asked for so there is no
- conversion time to speak of. The result is a smaller and faster
- program without much loss of readability.
-
- 5 Functions
-
- This library provides the same two flavors of functions that most
- C++ class libraries do: Member functions and non-member functions.
- The big difference is that member functions are called through their
- string object (like S.Left(3)) while non-member functions are called
- directly (like LeftText(S,3)). Operators, which are a form of a
- function, like '+', '=' and '<', kinda look and act like they're
- non-member functions, but are usually member functions cuz when the
- C++ compiler sees them it will usually break them into a member
- function of one of the operands: "S1<S2" will get thrown into
- something that looks like "S1.LessThan(S2)" (or, more realistically,
- "S1.operator<(S2)").
-
- 5.1 String class member functions
-
- The main thing to remember when using these functions and operators
- is that it should *seem* to be the way that you want to manipulate
- the string. If you're just getting started you might try looking at
- sections 5.1.1, 5.1.3 and then using the library. After using it a
- bit, come back and read the rest so that you can get more
- functionality and perhaps optimize things a bit more.
-
- 5.1.1 declaring a String
-
- Don't let all of these extra operators for constructing a String
- scare you off. These are mostly just extra whistles and bells
- provided for optimizing existing code. For the most part, all of
- your string declarations will probably be of the form
-
- String S1="some text"; // S1 is now "some text"
- String S2='X'; // S2 is now "X"
- String S3=""; // S3 is now empty
- String S4=S1; // S4 is now "some text"
- String S5=S1+S2; // S5 is now "some textX"
-
- 5.1.1.1 based on a given string constant or char*
-
- This is the String constructor that will probably be used more than
- all the others combined. Maybe even as much as 95% of the time.
- Although the preferred syntax is
-
- String S="some text";
-
- the syntax
-
- String S("some text");
-
- may also be used.
-
- 5.1.1.2 based on a character
-
- Initializing a String to a single character may be done with either
- of these two formats
-
- String S1='x';
- String S2('x');
-
- the preferred method being the first. To initialize a string to a
- certain length stuffed with a certain character, you must use the
- second method followed by the length you want the string to be:
-
- String S3('x',5); // S3 is now "xxxxx"
-
- 5.1.1.3 based on another String
-
- "String S2=S1;" or "String S2(S1);" where S1 is predeclared of
- type String.
-
- 5.1.1.4 without initialization
-
- I think that
-
- String S="";
-
- is the best notation, although
-
- String S;
-
- can also be used.
-
- Don't use
-
- String S();
-
- cuz the compiler will think that you have just declared a function
- called "S" that takes no parameters and returns a String.
-
- 5.1.1.5 extra allocation
-
- This feature is provided ONLY as an optimization technique. It
- should not be used for all programming, especially by those just
- starting out. Although using it does no harm, it adds more to read
- in the program and thus makes the program less readable to the
- beginner. I advise not using this feature except in those areas
- where the time or space savings are crucial ("The fastest algorithm
- can frequently be replaced by one that is almost as fast and much
- easier to understand" -- ACM programming pearls).
-
- When a string is constructed, a piece of memory is allocated to
- store the actual string. Generally, a little more memory than what
- is immediately needed is provided in case the string does a little
- growing.
-
- Should the programmer decide that time is a critical element and
- knows that a string will be expanded beyond it's initial size by,
- say, 30 characters, they may specify in the String constructor that
- room for 30 extra characters needs to be allocated so that the
- string won't need to be re-allocated later.
-
- Another case is when the space is a critical element and the
- programmer knows that the string will not become any larger. It can
- then be specified in the String constructor that no additional room
- for growth should be allocated.
-
- The above 4 constructors may all be expanded to have an additional
- parameter that will say how much more space should be allocated at
- initialization time. The following examples all show an additional
- allocation for 30 characters.
-
- 1: String S("some text",30);
- In this example, re-allocation will not occur until the string
- grows beyond 39 characters in size.
-
- 2: String S('x',5,30);
- Note here that three parameters are required to achieve extra
- allocation. If you want to initialize your string to a single
- character with thirty extra characters worth of memory allocated
- you must use ('x',1,30). ('x',30) will initialize a string of
- 30 'x's and the default extra allocation.
-
- 3: String S(S2,30);
- 4: String S(30);
-
- At this writing, the default amount of extra allocation is 15
- characters. This will probably change as time passes and this
- library becomes implemented on different systems.
-
- Keep in mind that the amount of memory allocated to hold a string is
- different from the length of the string (which is always shorter).
- Also keep in mind that when referring to the amount of memory
- allocated, that value is strictly for string text, not a null
- terminator, a length indicator or any other information. When a
- String is allocated for 3 characters and is assigned to be "abc",
- re-allocation does not occur.
-
- 5.1.2 Length() or Size()
-
- Prototype: int Length()
- int Size()
-
- These two functions are very similar, yet care needs to used in
- differentiating between the two. Both take the same parameters
- (none) and return the same type (int).
-
- Length() works like the ANSI C function strlen. It returns the
- number of characters in the current string. This function is much
- faster than strlen.
-
- Size() returns the number of bytes needed to store this string
- object on disk. This value is generally greater than the value
- returned by Length() and the amount of difference will change for
- different versions of this library on different machines (for
- example, some systems will seperate strings with a carriage return
- while others use a carriage return followed by a line feed). I
- mention all of this cuz sometimes a programmer may notice a trend
- (perhaps that in their experience Size() has always returned a value
- one greater than Length()) and try to take advantage of it, only to
- have it haunt them later.
-
- 5.1.3 + (concatenation)
-
- This is the one thing that I like about this library (and C++) more
- than any other. When you need to concatenate a whole mess of strings
- together, you simply put a "+" between them. You can even mix
- String types with char* and char types.
-
- char* S1="aa";
- String S2="bb";
- String S3=S1+S2+"cc"; // S3 is now "aabbcc"
-
- The only catch with all this is that a programmer would be tempted
- to do something like
-
- String S3=S1+"cc"; // error!!!
-
- in this case, the compiler tries to first evaluate S1+"cc" which are
- both pointers to a character. Since pointers are not allowed to be
- added to pointers, the compiler will return an error. The solution
- is to somehow mix a string into the concatenation list. In this
- example, the best way would be to first convert S1 to a string
-
- String S3=String(S1)+"cc"; // S3 is now "aacc"
-
- 5.1.4 += (appending form of concatenation)
-
- Given
-
- char* S1="aa";
- String S2="bb";
-
- then
-
- S2+=S1; // S2 is now "bbaa"
-
- however
-
- S1+=S2; // error!!!
-
- will not work. Remember that S1 is essentially a pointer. Trying
- to increment a pointer by an object doesn't make much sense and
- programmers are not allowed to modify or overload operators for
- built-in (atomic) types.
-
- 5.1.5 = (assignment) and conversions
-
- Another great thing that this library provides over ANSI C is simple
- string assignment. With S1 and S2 of type String, "S1=S2" will give you
- two equal, yet unique *Strings*. Modifications to S1 will not alter S2!
- Also strings of type String may take assignment from strings of type
- char*, a character, a character constant or a string constant.
- Respectively:
-
- char* S1="aa";
- char C1='b';
- String S2;
- S2=S1;
- S2=C1;
- S2='c';
- S2="dd";
-
- Conversely, partial access to a String is allowed as char*. The only
- "catch" is that the user must declare the receiving pointer as type
- "const char*". This is to protect the internal representation, or
- allocated copy of, the String type string. Most functions which accept a
- parameter of type char*, specify that parameter prefaced with "const", so
- the string may be passed directly and the converter will automatically
- pass the appropriate pointer without reservations. Given
-
- void Foo(const char*);
- void Bar(char*);
- String S="bar";
-
- the code "Foo(S)" would be fine, but "Bar(S)" would result in an
- error because S could not be converted. Since Bar does not specify
- that it will not modify the string that is passed to it, then it may
- do so and thus screw up the handling of S by this library.
-
- Copying a string of type String to a string of type char* should be done
- using the ANSI C strcpy or (preferably) strncpy functions:
-
- String S1="Foo";
- char S2[10];
- strncpy(S2,S1,sizeof(S2));
-
- 5.1.6 ==,!=,<,>,<=,>= (comparison)
-
- These operators simply call the ANSI C strcmp function. They are
- provided for higher readability ("S1<S2" replaces "strcmp(S1,S2)<0").
-
- 5.1.7 () or At() (retrieving substrings)
-
- Prototype: String At(int Index, int Length)
- char At(int Index)
-
- String S1="FooBar";
- String S2=S1(1,3); // S2 is now "ooB"
-
- Note that the parens can be prefixed with "At" if desired. The
- above line could then read
-
- String S2=S1.At(1,3); // S2 is now "ooB"
-
- The second parameter is optional. If it's left out, a single char
- is returned.
-
- String S2=S1.At(3); // S2 is now "B"
- char C=S1.At(3); // C is now 'B'
-
- 5.1.7.1 Before(), Through(), From() and After()
-
- Prototype: String Before(int Index)
- String Through(int Index)
- String From(int Index)
- String After(int Index)
-
- Four quickie functions that can add a little readability to your
- substring retrieval.
-
- String S1="abcdefghijk";
- String S2=S1.Before(5); // S2 is now "abcde"
- String S3=S1.Through(5); // S3 is now "abcdef"
- String S4=S1.From(5); // S4 is now "fghijk"
- String S5=S1.After(5); // S5 is now "ghijk"
-
- 5.1.8 [] (String char reference)
-
- Use this just as you would use it on an ANSI C style string.
-
- String S="FooBar";
- S[0]=S[3]; // S is now "BooBar"
-
- This indexing is completely safe. As could be expected, referencing
- beyond the end of the string will probably not do what you want
- (although all data will remain safe). If you assign a null ('\0' or
- 0) to a character in the string, you will confuse the string
- handler. If you want to truncate the string, call Left.
-
- 5.1.9 Left(), Right(), Center(), Just() (justification)
-
- Prototype: void Left(int NewSize)
- void Right(int NewSize)
- void Center(int NewSize)
- void Just(SByte Type, int NewSize)
-
- Left, Right and Center all take one paramater, the new size of the
- string desired. If the size of the string is larger than the new
- size desired, the right part of the string is truncated. Otherwise,
- the string is padded with spaces to bring the string up to the new
- size desired.
-
- Examples:
-
- String S="Foo";
- S.Left(1); // S is now "F"
- S.Left(3); // S is now "F "
- S="Foo"; // S is now "Foo"
- S.Right(5); // S is now " Foo"
- S.Right(3); // S is now " F"
- S="Foo"; // S is now "Foo"
- S.Center(5); // S is now " Foo "
-
- The function "Just" simply acts as a parser
-
- S="Foo";
- S.Just(Center,5); // S is now " Foo "
-
- 5.1.10 Capacity() (report current allocation)
-
- Prototype: int Capacity()
-
- Simply reports how many characters long the string can get without
- having to re-allocate.
-
- 5.1.11 ReAlloc() (change capacity)
-
- Prototype: int ReAlloc(int NewCapacity)
-
- Will perform a re-allocation to the capacity required. You might
- use this to prevent future multiple re-allocation.
-
- 5.1.12 ToLower() (force all upper case letters to lower case)
-
- Prototype: void ToLower()
-
- 5.1.13 ToUpper() (force all lower case letters to upper case)
-
- Prototype: void ToUpper()
-
- 5.1.14 Index() (find the index of a char)
-
- Prototype: int Index(char SearchChar, int StartIndex=0)
-
- Starting at StartIndex, the string will be searched until SearchChar
- is found or the end of the string is reached. If SearchChar is
- found, the function returns the index to the char, otherwise the
- function will return the constant "NotFound".
-
- 5.1.15 Insert() (insert a char or a sting into the string)
-
- Prototype: void Insert(char C,int Index=0)
- void Insert(const char* St,int Index=0)
-
- String S="abcdefghijk";
- S.Insert('X',3); // S is now "abcXdefghijk"
- S.Insert("ZZZ",1); // S is now "aZZZbcXdefghijk"
- S.Insert("AA"); // S is now "AAaZZZbcXdefghijk"
- // S="AA"+S would be more readable I think
-
- 5.1.16 Delete() (delete characters from the string)
-
- Prototype: void Delete(int Index=0,int Length=1)
-
- String S="abcdefghijk";
- S.Delete(1,2); // S is now "adefghijk"
-
- 5.2 non-member functions
-
- These functions add a lot of coding convenience since they all
- return strings without the need of preallocated space. They can be
- used directly in functions that ask for a string without having an
- intermediate storage identifier:
-
- void Foo(const char*);
- String Str(long);
- ...
- Foo(Str(10000));
-
- In ANSI C, you would have to first declare a temporary string big
- enough to store the result of "Str", pass the string to "Str" and
- then pass the result, which is stored in your string, to "Foo".
-
- 5.2.1 Str() (convert integers to String)
-
- Prototype: String Str(long)
-
- Examples:
-
- int B=3;
- String S=Str(B); // S is now "3"
- S=Str(999999); // S is now "999999"
- S=Str(-99999); // S is now "-99999"
-
- 5.2.2 Form() (convert reals to a String using a format)
-
- Prototype: String Form(const char* Format,double Val)
- String Form(int FLen,long Val)
-
- You pass a legal format and a number to fit in it, and you'll get a
- string back that is the same length as your format and has your
- number properly arranged in it.
-
- Characters that can be used are:
-
- '#' a number, or a space if left of decimal, 0 if right
- '@' same as '#' cept is 0 if there is no number
- '.' defines the decimal place, if any. May only be one
- ',' a comma place holder
-
- The characters '<' and '>' may be used to show negation. They must
- both be used with '<' as the first character in the string and '>'
- as the last.
-
- Examples:
-
- String S=Form("##",12.4); // S is now "12"
- S=Form("<###,###.##>",-12.4); // S is now "< 12.40>"
- S=Form("<###,###.##>", 12.4); // S is now " 12.40 "
- S=Form("@@@@@", 12.4); // S is now "00012"
- S=Form("@@@@@", -12.4); // S is now "-0012"
- S=Form("#####", -12.4); // S is now " -12"
- S=Form("@@@@@.@@", 12.4); // S is now "00012.40"
- S=Form("###,###.##", 12345); // S is now " 12,345.00"
- S=Form("##", 123); // S is now "**"
-
- The first parameter may also be a number...
-
- S=Form( 6, 1234); // S is now " 1,234"
- S=Form( 4, 1234); // S is now "1234"
- S=Form( 2, 1234); // S is now "**"
- S=Form(-6, 1234); // S is now " 1234 "
- S=Form(-6,-1234); // S is now "<1234>"
- S=Form(-7,-1234); // S is now "<1,234>"
- S=Form( 6,-12.3); // S is now " -12"
-
- If the first parameter is a number, then the second must be an
- integer (or it will be converted to one).
-
- 5.2.3 StringOf() (return a string of chars)
-
- Prototype: String StringOf(int HowMany, char OfWhat)
-
- To remember the parameters of this think of "I want a string of
- twenty periods", so you make the function call "StringOf(20,'.')".
- To help remember the string constructor parameters (a very different
- thing!), remember that it's based on the char and the number of
- those chars is optional, so the char must come first.
-
- String S=StringOf(5,'x'); // S is now "xxxxx"
- String S('x',5); // S is now "xxxxx"
-
- 5.2.4 Spaces() (return a String containing a certain number of spaces)
-
- Prototype: String Spaces(int HowMany)
-
- 5.2.5 LeftText(), RightText(), CenterText(), JustText()
-
- Prototype: String LeftText(const char* CS, int NewSize)
- String RightText(const char* CS, int NewSize)
- String CenterText(const char* CS, int NewSize)
- String JustText(const char* CS, SByte Type, int NewSize)
-
- Remarkably similar to the String member functions Left, Right,
- Center and Just.
-